package controller

import (
	"Founction/forms"
	"Founction/global"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/go-redis/redis"
	"net/http"
	"strconv"
)

func GetRanking(c *gin.Context) {
	// 直接从Redis获取排行榜数据
	rdb := global.Redis
	zrangeCmd := rdb.ZRevRangeWithScores("scores", 0, 9) // 获取前10名
	if err := zrangeCmd.Err(); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to fetch ranking from Redis"})
		return
	}

	var rankings []forms.RankingItem
	for _, member := range zrangeCmd.Val() {
		rankings = append(rankings, forms.RankingItem{
			UserID: member.Member.(string),
			Score:  member.Score,
		})
	}

	c.JSON(http.StatusOK, rankings)
}

func UpdateScoreAndSync(c *gin.Context) {
	// 更新MySQL
	userID, _ := strconv.Atoi(c.Param("user_id"))
	newScore, _ := strconv.Atoi(c.Param("new_score"))
	DB := global.DB
	// 尝试更新MySQL
	if err := UpdateUserScoreInMySQL(userID, newScore); err != nil {
		DB.Rollback()

	}

	// 直接传递 redis.Z 的值给 ZAdd

	// 同步到Redis
	if err := updateScoreAndSyncInRedis(userID, newScore); err != nil {
		fmt.Println("Failed to sync score to Redis:", err)
	}
}

// UpdateUserScoreInMySQL 更新用户在MySQL中的分数
func UpdateUserScoreInMySQL(userID int, newScore int) error {
	// 准备SQL更新语句
	updateStmt := `
        UPDATE users_scores
        SET score = ?
        WHERE user_id = ?
    `

	// 执行更新操作
	result := global.DB.Exec(updateStmt, newScore, userID)

	// 可选：检查影响的行数，确保更新操作成功
	rowsAffected := result.RowsAffected

	if rowsAffected == 0 {
		return fmt.Errorf("no rows were updated for user ID %d", userID)
	}

	return nil
}

// updateScoreAndSyncInRedis 更新Redis中的用户分数
func updateScoreAndSyncInRedis(userID int, newScore int) error {
	// 将用户ID转换为字符串，因为Redis的ZSet成员需要是字符串类型
	userIDStr := strconv.Itoa(userID)

	// 使用ZADD命令更新或添加用户分数到有序集合
	// XX选项如果不存在则不执行操作，这里未使用，因为我们总是想更新或插入
	// CH选项仅当分数发生变化时才更新成员，但根据需求，我们总是更新最新的分数
	rdb := global.Redis
	if newScore >= 0 { // 假设分数不会是负数，如果是负数可能需要特殊处理
		scoreMember := redis.Z{Score: float64(newScore), Member: userIDStr}
		cmd := rdb.ZAdd("scores", scoreMember)
		if err := cmd.Err(); err != nil {
			return err
		}
	} else {
		// 处理负分数的逻辑，比如可能是删除操作
		rdb.ZRem("scores", userIDStr)
	}
	return nil
}
